package user_handler

import (
	"net/http"
	"peilian-api/app/global/bind"
	"peilian-api/app/global/databases/tables"
	"peilian-api/app/global/errors"
	"peilian-api/app/global/log"
	"peilian-api/app/global/variable"
	"peilian-api/app/model"
	"peilian-api/app/services"
	"peilian-api/app/services/conf_service"
	"peilian-api/app/services/user_service"
	"peilian-api/utils/format"
	"peilian-api/utils/tools"

	"github.com/gin-gonic/gin"
)

// 发送验证码
func SendCode(ctx *gin.Context) {
	var sc model.SendCodeRequest
	if err := bind.ShouldBinding(ctx, &sc); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	if err := user_service.SendCode(ctx, sc); err != nil {
		format.NewResponseJson(ctx).Err(10001, err.Error())
		return
	}
	format.NewResponseJson(ctx).Success(make([]interface{}, 0))
}

// 小程序绑定邮箱获取验证码
func MailSendCode(ctx *gin.Context) {
	var sc model.MailSendCodeRequest
	if err := bind.ShouldBinding(ctx, &sc); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	if err := user_service.MailSendCode(ctx, sc); err != nil {
		format.NewResponseJson(ctx).Err(10001, err.Err.Error())
		return
	}
	format.NewResponseJson(ctx).Success(make([]interface{}, 0))
}

// 小程序邮箱找回密码-获取验证码
func MailSendCodeFind(ctx *gin.Context) {
	var sc model.MailSendCodeRequest
	if err := bind.ShouldBinding(ctx, &sc); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	if err := user_service.MailSendCodeFind(ctx, sc); err != nil {
		format.NewResponseJson(ctx).Err(10001, err.Err.Error())
		return
	}
	format.NewResponseJson(ctx).Success(make([]interface{}, 0))
}

// 小程序解除绑定邮箱获取验证码
func DelMail(ctx *gin.Context) {
	out, err := user_service.DelMail(ctx)
	if err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	format.NewResponseJson(ctx).SuccessObj(out)
}

// 用户打开小程序回调：由小程序端监听用户是否打开小程序，打开后回调本接口进行记录
func OpenCallback(c *gin.Context) {
	uid, exist := c.Get("uid")
	if !exist {
		tools.Resp400(c, "获取用户失败")
		return
	}
	if err := variable.DB.MySQL.Create(&tables.UserLoginLog{UserID: uid.(uint), Type: "open"}).Error; err != nil {
		tools.Resp400(c, err.Error())
		return
	}
	format.NewResponseJson(c).Success(make([]interface{}, 0))
}

// 小程序登录
func Login(ctx *gin.Context) {
	var lr model.LoginRequest
	if err := bind.ShouldBinding(ctx, &lr); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	u, err := user_service.Login(ctx, lr, lr.Type, lr.PromoteId)
	if err != nil {
		log.Logger.InfoF(ctx, err.Error())
		// log.Logger.InfoF(ctx, err.Error())
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}

	variable.DB.MySQL.Create(&tables.UserLoginLog{UserID: uint(u.Id), Type: "login"})
	format.NewResponseJson(ctx).SuccessObj(u)
}

// BoxLogin 盒子端的登录
func BoxLogin(ctx *gin.Context) {
	var sc model.ScLogin
	if err := bind.ShouldBinding(ctx, &sc); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	u, err := user_service.BoxLogin(ctx, sc)
	if err != nil {
		log.Logger.InfoF(ctx, err.Error())
		// log.Logger.InfoF(ctx, err.Error())
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}

	variable.DB.MySQL.Create(&tables.UserLoginLog{UserID: uint(u.Id), Type: "login"})
	format.NewResponseJson(ctx).SuccessObj(u)
}

// UserVerify 用户验证(不返回token 只做验证)
func UserVerify(ctx *gin.Context) {
	var sc user_service.UserVerifyReq
	if err := bind.ShouldBinding(ctx, &sc); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	u, err := user_service.UserVerify(ctx, sc)
	if err != nil {
		log.Logger.InfoF(ctx, err.Error())
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}

	variable.DB.MySQL.Create(&tables.UserLoginLog{UserID: u.ID, Type: "UserVerify"})
	format.NewResponseJson(ctx).SuccessObj(u)
}

// ThirdLogin 第三方的登录
func ThirdLogin(ctx *gin.Context) {
	var sc model.ScLogin
	if err := bind.ShouldBinding(ctx, &sc); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	u, err := user_service.ThirdLogin(ctx, sc)
	if err != nil {
		log.Logger.InfoF(ctx, err.Error())
		// log.Logger.InfoF(ctx, err.Error())
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}

	variable.DB.MySQL.Create(&tables.UserLoginLog{UserID: uint(u.Id), Type: "login"})
	format.NewResponseJson(ctx).SuccessObj(u)
}

// 用户端的登出
func Logout(ctx *gin.Context) {
	u, err := user_service.Logout(ctx)
	if err != nil {
		log.Logger.InfoF(ctx, err.Error())
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}

	variable.DB.MySQL.Create(&tables.UserLoginLog{UserID: uint(u.Id), Type: "logout"})
	format.NewResponseJson(ctx).SuccessObj("")
}

// 补全用户信息
func UserInfo(ctx *gin.Context) {
	var ui model.UserInfoRequest
	if err := bind.ShouldBinding(ctx, &ui); err != nil {
		format.NewResponseJson(ctx).Err(errors.RequestParamsBindCode, err.Error())
		return
	}
	if err := user_service.UserInfo(ctx, ui, ui.Uid); err != nil {
		format.NewResponseJson(ctx).Err(err.Code, err.Err.Error())
		return
	}
	format.NewResponseJson(ctx).Success(make([]interface{}, 0))
}

// 获取用户信息，目前主要是用户头像和用户名称
func GetUserInfo(c *gin.Context) {
	userId, exist := c.Get("uid")
	if !exist {
		format.NewResponseJson(c).Err(http.StatusBadRequest, "token有误，请检查登录信息")
		return
	}
	var user tables.User
	if err := variable.DB.MySQL.First(&user, userId).Error; err != nil {
		format.NewResponseJson(c).Err(http.StatusBadRequest, "该用户不存在")
		return
	}
	if user.IconUrl != "" {
		user.IconUrl = variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix + user.IconUrl
	}
	user.Token = c.Request.Header.Get("AuthenticationToken")
	format.NewResponseJson(c).SuccessObj(user)
}

// 更改用户信息, 目前主要是用户头像和用户名称
func UpdateUserInfo(c *gin.Context) {
	userId, exist := c.Get("uid")
	if !exist {
		format.NewResponseJson(c).Err(http.StatusBadRequest, "token有误，请检查登录信息")
		return
	}
	var user tables.User
	if err := variable.DB.MySQL.First(&user, userId).Error; err != nil {
		format.NewResponseJson(c).Err(http.StatusBadRequest, err.Error())
		return
	}
	if user.Type != tables.UserTypeAnonymous {
		format.NewResponseJson(c).Err(http.StatusBadRequest, "您不是游客，不能修改")
		return
	}
	updateFields := make([]string, 0)
	if _, err := c.FormFile("photo"); err == nil {
		filePath, err := services.ExtractFormFile(c)
		if err != nil {
			format.NewResponseJson(c).Err(http.StatusBadRequest, err.Err.Error())
			return
		}
		user.IconUrl = filePath
		updateFields = append(updateFields, "IconUrl")
	} else {
		var uq model.UserInfoRequest
		_ = c.ShouldBindJSON(&uq)
		if uq.Name != "" {
			user.Name = uq.Name
			updateFields = append(updateFields, "Name")
		}
	}
	if err := variable.DB.MySQL.Model(&user).Select(updateFields).Updates(&user).Error; err != nil {
		format.NewResponseJson(c).Err(http.StatusInsufficientStorage, err.Error())
		return
	}
	if user.IconUrl != "" {
		user.IconUrl = variable.Config.UfsInfo.UfsUrl + variable.Config.UfsInfo.BucketPrefix + user.IconUrl
	}
	// 更新用户信息
	_, err := user_service.SetUserInfo(c, userId.(uint))
	if err != nil {
		format.NewResponseJson(c).Err(http.StatusInsufficientStorage, err.Err.Error())
		return
	}
	user.Token = c.Request.Header.Get("AuthenticationToken")
	format.NewResponseJson(c).SuccessObj(user)
}

// 后台管理系统登录
func AdminLogin(ctx *gin.Context) {
	var sc model.SendCodeRequest
	if err := bind.ShouldBinding(ctx, &sc); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	lr, err := user_service.UserLogin(ctx, sc)
	if err != nil {
		format.NewResponseJson(ctx).Err(30002, err.Error())
		return
	}
	format.NewResponseJson(ctx).SuccessObj(lr)
}

// 获取人员类型
func GetStafList(ctx *gin.Context) {
	cs := new(conf_service.ConfService)
	eductionList := cs.GetStafList()
	format.NewResponseJson(ctx).SuccessObj(eductionList)
}

// 小程序绑定手机号
func BindingPhone(ctx *gin.Context) {
	var bp model.BindingPhone
	if err := bind.ShouldBinding(ctx, &bp); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	out, err := user_service.BindingPhone(ctx, bp)
	if err != nil {
		format.NewResponseJson(ctx).Err(30002, err.Error())
		return
	}
	format.NewResponseJson(ctx).SuccessObj(out)
}

func BindingSync(ctx *gin.Context) {
	var bp model.BindingSync
	if err := bind.ShouldBinding(ctx, &bp); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	out, err := user_service.BindingSync(ctx, bp)
	if err != nil {
		format.NewResponseJson(ctx).Err(30002, err.Error())
		return
	}

	format.NewResponseJson(ctx).SuccessObj(out)
}

// 小程序绑定邮箱
func BindingMail(ctx *gin.Context) {
	var bp model.BindingMail
	if err := bind.ShouldBinding(ctx, &bp); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	out, err := user_service.BindingMail(ctx, bp)
	if err != nil {
		format.NewResponseJson(ctx).Err(30002, err.Error())
		return
	}
	format.NewResponseJson(ctx).SuccessObj(out)
}

// 小程序邮箱找回密码
func ConfirmFind(ctx *gin.Context) {
	var bp model.BindingMail
	if err := bind.ShouldBinding(ctx, &bp); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	err := user_service.ConfirmCode(ctx, bp)
	if err != nil {
		format.NewResponseJson(ctx).Err(30002, err.Error())
		return
	}
	format.NewResponseJson(ctx).SuccessObj(struct{}{})
}

// 小程序重置密码
func ResetPwd(ctx *gin.Context) {
	var pr model.PwdReset
	if err := bind.ShouldBinding(ctx, &pr); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	err := user_service.ResetPwd(ctx, pr)
	if err != nil {
		format.NewResponseJson(ctx).Err(30002, err.Err.Error())
		return
	}
	format.NewResponseJson(ctx).SuccessObj(struct{}{})
}

// 小程序找回密码-重置密码
func ResetPwdFind(ctx *gin.Context) {
	var pr model.PwdResetFind
	if err := bind.ShouldBinding(ctx, &pr); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	err := user_service.ResetPwdFind(ctx, pr)
	if err != nil {
		format.NewResponseJson(ctx).Err(30002, err.Err.Error())
		return
	}
	format.NewResponseJson(ctx).SuccessObj(struct{}{})
}

// 获取当前用户的信息
func GetCurrentUserInfo(ctx *gin.Context) {
	// 1. 获取当前用户的uid
	out, err := user_service.GetCurrentUserInfo(ctx)
	if err != nil {
		format.NewResponseJson(ctx).Err(err.Code, err.Err.Error())
		return
	}
	if out.Token == "" {
		out.Token = ctx.Request.Header.Get("AuthenticationToken")
	}
	format.NewResponseJson(ctx).SuccessObj(out)
}

// 获取用户上新题目是否需要弹窗
func GetNotificationTopicNew(ctx *gin.Context) {
	b, err := user_service.GetNotificationTopicNew(ctx)
	if err != nil {
		format.NewResponseJson(ctx).Err(30002, err.Error())
		return
	}
	format.NewResponseJson(ctx).SuccessObj(struct {
		TopicNew bool `json:"topic_new"`
	}{
		TopicNew: b,
	})
}

// 添加企业信息
func AddEnterprise(ctx *gin.Context) {
	var ep model.EnterpriseInfo
	if err := bind.ShouldBinding(ctx, &ep); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	b, err := user_service.AddEnterprise(ctx, ep)
	if err != nil {
		format.NewResponseJson(ctx).Err(30002, err.Error())
		return
	}
	format.NewResponseJson(ctx).SuccessObj(b)
}

// 小程序登录
func TokenVerify(ctx *gin.Context) {
	var req model.TokenVerifyReset
	if err := bind.ShouldBinding(ctx, &req); err != nil {
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	timeStep, err := user_service.VerifyToken(ctx, req)
	if err != nil {
		log.Logger.InfoF(ctx, err.Error())
		format.NewResponseJson(ctx).Err(30001, err.Error())
		return
	}
	format.NewResponseJson(ctx).SuccessObj(map[string]string{"timeStep": timeStep})
}
